#!/usr/bin/env node

/**
 * 恢复已预约状态的数据脚本
 *
 * 从源数据库恢复状态为 'booked' 的预约数据到目标数据库
 * 如果目标数据库中已存在重复数据（以证件号码+驾照号码+姓名为唯一标准），则跳过
 *
 * 使用方法：
 *   node app/scripts/restore-booked-appointments.mjs
 *   node app/scripts/restore-booked-appointments.mjs --dry-run
 */

import { existsSync } from 'node:fs'

// 源数据库路径
const sourceDbPath = 'C:\\projects\\scriptWork\\auto-tools\\app\\prisma\\data\\app.db'
// 目标数据库路径
const targetDbPath = 'C:\\Users\\Administrator\\AppData\\Roaming\\AutoTools\\data\\app.db'

/**
 * 生成唯一标识（证件号码+驾照号码+姓名）
 */
function getUniqueKey(record) {
  const passport = String(record.passport_number || '').trim().toUpperCase()
  const license = String(record.license_number || '').trim().toUpperCase()
  const name = String(record.full_name || '').trim()
  return `${passport}|${license}|${name}`
}

async function main() {
  // 解析命令行参数
  let dryRun = false

  for (let i = 2; i < process.argv.length; i++) {
    const arg = process.argv[i]
    if (arg === '--dry-run') {
      dryRun = true
    }
  }

  if (dryRun) {
    console.log('🔍 预览模式：不会实际修改数据\n')
  }

  // 检查源数据库是否存在
  if (!existsSync(sourceDbPath)) {
    console.error(`❌ 源数据库文件不存在: ${sourceDbPath}`)
    process.exit(1)
  }

  // 检查目标数据库是否存在
  if (!existsSync(targetDbPath)) {
    console.error(`❌ 目标数据库文件不存在: ${targetDbPath}`)
    process.exit(1)
  }

  console.log('正在初始化数据库连接...')
  const { PrismaClient } = await import('@prisma/client')

  // 初始化源数据库连接
  const sourceDbUrl = `file:${sourceDbPath.replace(/\\/g, '/')}`
  const sourcePrisma = new PrismaClient({
    datasources: {
      db: { url: sourceDbUrl },
    },
  })

  // 初始化目标数据库连接
  const targetDbUrl = `file:${targetDbPath.replace(/\\/g, '/')}`
  const targetPrisma = new PrismaClient({
    datasources: {
      db: { url: targetDbUrl },
    },
  })

  // 启用 WAL 模式
  try {
    await sourcePrisma.$executeRawUnsafe('PRAGMA journal_mode=WAL;')
    await sourcePrisma.$executeRawUnsafe('PRAGMA synchronous=NORMAL;')
    await sourcePrisma.$executeRawUnsafe('PRAGMA busy_timeout=15000;')
    await targetPrisma.$executeRawUnsafe('PRAGMA journal_mode=WAL;')
    await targetPrisma.$executeRawUnsafe('PRAGMA synchronous=NORMAL;')
    await targetPrisma.$executeRawUnsafe('PRAGMA busy_timeout=15000;')
  }
  catch {}

  console.log(`✅ 源数据库: ${sourceDbPath}`)
  console.log(`✅ 目标数据库: ${targetDbPath}`)
  console.log()

  try {
    // 从源数据库查询所有已预约状态的数据
    console.log('正在从源数据库查询已预约状态的数据...')
    const sourceRecords = await sourcePrisma.appointment_management.findMany({
      where: {
        appointment_status: 'booked',
      },
      orderBy: {
        id: 'asc',
      },
    })

    console.log(`找到 ${sourceRecords.length} 条已预约状态的记录\n`)

    if (sourceRecords.length === 0) {
      console.log('✅ 源数据库中没有需要恢复的记录')
      return
    }

    // 从目标数据库查询所有记录，建立唯一标识索引
    console.log('正在从目标数据库查询现有记录...')
    const targetRecords = await targetPrisma.appointment_management.findMany({
      select: {
        passport_number: true,
        license_number: true,
        full_name: true,
      },
    })

    // 建立目标数据库的唯一标识集合
    const targetKeys = new Set(targetRecords.map(record => getUniqueKey(record)))
    console.log(`目标数据库中已有 ${targetKeys.size} 条记录\n`)

    // 过滤出需要恢复的记录（不重复的，且参考编号以5122开头）
    const recordsToRestore = sourceRecords.filter((record) => {
      // 检查是否重复
      const key = getUniqueKey(record)
      if (targetKeys.has(key)) {
        return false
      }

      // 检查参考编号是否以5122开头
      const refNumber = String(record.reference_number || '').trim()
      if (!refNumber.startsWith('5122')) {
        return false
      }

      return true
    })

    const skippedCount = sourceRecords.length - recordsToRestore.length

    // 统计过滤原因
    const duplicateCount = sourceRecords.filter(record => targetKeys.has(getUniqueKey(record))).length
    const invalidRefCount = sourceRecords.filter((record) => {
      const refNumber = String(record.reference_number || '').trim()
      return !refNumber.startsWith('5122')
    }).length

    console.log('─'.repeat(100))
    console.log('统计信息:')
    console.log(`  源数据库记录数: ${sourceRecords.length}`)
    console.log(`  目标数据库记录数: ${targetKeys.size}`)
    console.log(`  需要恢复的记录数: ${recordsToRestore.length}`)
    console.log(`  跳过（重复）的记录数: ${duplicateCount}`)
    console.log(`  跳过（参考编号非5122开头）的记录数: ${invalidRefCount}`)
    console.log(`  总计跳过: ${skippedCount}`)
    console.log('─'.repeat(100))
    console.log()

    if (recordsToRestore.length === 0) {
      console.log('✅ 所有记录在目标数据库中都已存在，无需恢复')
      return
    }

    // 显示前几条记录预览
    console.log('预览（前10条待恢复记录）:')
    console.log('─'.repeat(100))
    console.log(
      'ID'.padEnd(8),
      '姓名'.padEnd(20),
      '证件号码'.padEnd(20),
      '驾照号码'.padEnd(20),
      '参考编号'.padEnd(20),
    )
    console.log('─'.repeat(100))
    recordsToRestore.slice(0, 10).forEach((record) => {
      console.log(
        String(record.id).padEnd(8),
        (record.full_name || '-').padEnd(20),
        (record.passport_number || '-').padEnd(20),
        (record.license_number || '-').padEnd(20),
        (record.reference_number || '-').padEnd(20),
      )
    })
    if (recordsToRestore.length > 10) {
      console.log(`... 还有 ${recordsToRestore.length - 10} 条记录`)
    }
    console.log('─'.repeat(100))
    console.log()

    if (dryRun) {
      console.log('🔍 预览模式：以上记录将被恢复到目标数据库')
      console.log('运行时不加 --dry-run 参数将实际执行恢复')
      return
    }

    // 确认操作
    console.log(`⚠️  即将恢复 ${recordsToRestore.length} 条记录到目标数据库`)
    console.log()

    // 执行批量恢复
    console.log('正在恢复数据...')
    let successCount = 0
    let failCount = 0

    // 使用批量插入提高效率
    const batchSize = 50
    for (let i = 0; i < recordsToRestore.length; i += batchSize) {
      const batch = recordsToRestore.slice(i, i + batchSize)

      try {
        // 准备批量插入数据
        const insertData = batch.map((record) => {
          // 复制所有字段，但移除 id（让数据库自动生成新ID）
          const { id, ...data } = record
          return data
        })

        // 使用事务批量插入
        await targetPrisma.$transaction(
          insertData.map(data =>
            targetPrisma.appointment_management.create({ data }),
          ),
        )

        successCount += batch.length

        if ((i + batchSize) % 200 === 0 || i + batchSize >= recordsToRestore.length) {
          console.log(`  已恢复 ${Math.min(i + batchSize, recordsToRestore.length)}/${recordsToRestore.length} 条...`)
        }
      }
      catch (error) {
        console.error(`❌ 批量恢复失败 (批次 ${Math.floor(i / batchSize) + 1}):`, error.message)
        // 如果批量插入失败，尝试逐条插入
        console.log('  尝试逐条恢复...')
        for (const record of batch) {
          try {
            const { id, ...data } = record
            await targetPrisma.appointment_management.create({ data })
            successCount++
          }
          catch (err) {
            // 检查是否是重复键错误
            if (err.message && err.message.includes('Unique constraint')) {
              console.log(`  ⚠️  记录已存在（跳过）: ${record.full_name || 'N/A'} - ${record.passport_number || 'N/A'}`)
              failCount++
            }
            else {
              console.error(`  ❌ 恢复记录失败: ID=${record.id}, 姓名=${record.full_name || 'N/A'}, 错误: ${err.message}`)
              failCount++
            }
          }
        }
      }
    }

    console.log()
    console.log('─'.repeat(100))
    console.log('✅ 恢复完成！')
    console.log(`   成功恢复: ${successCount} 条`)
    console.log(`   失败/跳过: ${failCount} 条`)
    console.log(`   源记录总数: ${sourceRecords.length} 条`)
    console.log(`   跳过（重复）: ${skippedCount} 条`)
    console.log('─'.repeat(100))
  }
  catch (error) {
    console.error('❌ 执行失败:', error)
    process.exit(1)
  }
  finally {
    await sourcePrisma.$disconnect()
    await targetPrisma.$disconnect()
  }
}

main().catch((error) => {
  console.error('❌ 脚本执行失败:', error)
  process.exit(1)
})
